﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace SerializationBinnary
{
    class Program
    {
        static void Main(string[] args)
        {
            User [] users = new[] 
            {
                new User ("Sasha"),
                new User ("Kolia"),
                new User ("Dima")
            };

            BinaryRepository<User> user = new BinaryRepository<User>();

            foreach (User i in users)
            {
                user.Insert(i);
            }

            user.Save();

            Console.WriteLine("список");
            var spisok = user.ChekOut();
            foreach (var i in spisok)
            {
                Console.WriteLine("человек {0} под {1}", i.Name, i.ID);
            }

            user.Delete(users[1]);

            user.Save();

            Console.WriteLine("список");
            spisok = user.ChekOut();
            foreach (var i in spisok)
            {
                Console.WriteLine("человек {0} под {1}", i.Name, i.ID);
            }

            Console.WriteLine(user.ReadByID("id1000").Name);

            Console.ReadLine();
        }
    }

    public abstract class Repository<T> where T : IEntity
    {
        protected Dictionary<string, T> local = new Dictionary<string,T>();

        public void Insert(T entity)
        {
            local.Add(entity.ID, entity);
        }

        public void Update(T entity)
        {
            if (local.ContainsValue(entity))
            {
                local[entity.ID] = entity;
            }
            else
            {
                throw new ArgumentException(String.Format("Не найдено записей, содержащих объект {0}", entity.ToString()));
            }
        }

        public void Delete(T entity)
        {
            if (local.ContainsKey(entity.ID))
            {
                local.Remove(entity.ID);
            }
            else
            {
                throw new ArgumentException(String.Format("Не найдено записей, содержащих объект {0}", entity.ToString()));
            }
        }

        public T ReadByID(string id)
        {
            if (local.ContainsKey(id))
            {
                return local[id];
            }
            else
            {
                throw new ArgumentException(String.Format("Не найдено записей по id = {0}", id));
            }
        }

        public abstract List<T> ChekOut();
        public abstract void Save();

    }

    public class BinaryRepository<T> : Repository<T> where T : IEntity 
    {
        public override List<T> ChekOut()
        {
            var format = new BinaryFormatter();
            using (Stream s = File.OpenRead("group.dat"))
            {
                local = (Dictionary<string, T>)format.Deserialize(s);
                return local.Values.ToList();

            }
        }

        public override void Save()
        {
            var format = new BinaryFormatter();
            using (Stream s = File.Create("group.dat"))
            {
                format.Serialize(s, local);
            }
        }
    }

    [Serializable]
    public class User : IEntity
    {
        private String _id;
        private static Int32 id = 1000;
        public String Name { get; set; }

        public User(String name)
        {
            _id = String.Format("id{0}", id++);
            Name = name;
        }

        public string ID
        {
            get
            {
                return _id;
            }
        }
    }

    public interface IEntity
    {
        string ID { get; }
    }
}
